#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

unsigned short port = 11002;
char ipaddr[16] = "127.0.0.1";
int child_count = 10;

void *thread_run (void *arg)
{
	int     sockfd , i, tolen;
	struct	sockaddr_in servaddr;
	struct timeval tv = {5, 0};
	
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port);
	inet_pton(AF_INET, ipaddr, &servaddr.sin_addr);
	tolen = sizeof (servaddr);

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof (tv)) != 0)
	{
		fprintf (stderr, "%s\n", strerror (errno));
	}

	printf ("thread %d run ... ...\n", getpid ());

	for (i = 0; i < 10000; i++)
	{
		char send_buf[1000],recv_buf[1000]; 
		int length;
		sprintf (send_buf, "%d %d", getpid (), i);
	//	length = strlen (send_buf) + 1;
		length = sizeof (send_buf);

		if (length != sendto (sockfd, send_buf, length, MSG_DONTWAIT, (const struct sockaddr*)&servaddr, tolen))
		{
			fprintf (stderr, "sendto error,pid=%d,count=%d\n",  getpid (), i);
			continue;
		}
recv_again:
		if (length != recvfrom (sockfd, recv_buf, length, 0, (struct sockaddr*)&servaddr, &tolen))
		{
			fprintf (stderr, "recvfrom error,pid=%d,count=%d,%s\n",  getpid (), i, strerror (errno));
			continue;
		}

		if (memcmp (recv_buf, send_buf, length) != 0)
		{
			fprintf (stderr, "strmcp error,send %s,recv %s\n",send_buf, recv_buf);
			goto recv_again;
		}
	}

	return NULL;
}

int main (int argc, char* argv[])
{
	int c, i;
	pthread_t *thread_tid ;
	for (; (c = getopt (argc, argv, "p:c:i:")) != -1;)
	{
		switch (c)
		{
			case 'c':
				child_count = atoi (optarg);
				break;
			case 'p':
				port = atoi (optarg);
				break;
			case 'i':
				strncpy (ipaddr, optarg, sizeof (ipaddr) - 1);
				break; 
		}
	}

	thread_tid = (pthread_t*)calloc (child_count, sizeof (pthread_t));
	for (i = 0; i < child_count; i++)
		pthread_create (&thread_tid[i], NULL, &thread_run, NULL);

	for (i = 0; i < child_count; i++)
		pthread_join (thread_tid[i], NULL);

	return 0;
}
